var Amqp = require('../amqp').Amqp;

/**
 * Work with queues.
 *
 * Queues store and forward messages. Queues can be configured in the server or created at runtime.
 * Queues must be attached to at least one exchange in order to receive messages from publishers.
 *
 * @class
 * @extends events.EventEmitter
 * @exports Queue as impl.Queue
 * @param handler
 */
function Queue(/**handlers.Channel*/handler){
    var queue = this;
    this.handler = handler;
    /**
     * Confirms a queue definition.
     *
     * This method confirms a Declare method and confirms the name of the queue, essential for
     * automatically-named queues.
     *
     * @name Queue#declare
     * @event
     * @param {String} queue The queue name identifies the queue within the vhost. Queue names may
     *      consist of any mixture of digits, letters, and underscores.
     * @param {Number} messageCount Reports the number of messages in the queue, which will be zero
     *      for newly-created queues.
     * @param {Number} consumerCount Reports the number of active consumers for the queue. Note
     *      that consumers can suspend activity (Channel.Flow) in which case they do not appear in
     *      this count.
     */
    handler.addListener('Amqp.Queue.DeclareOk', function(frame){
        var a = frame.method.arguments;
        queue.emit('declare', a.queue, a.messageCount, a.consumerCount);
    });
    /**
     * Confirm bind successful.
     *
     * This method confirms that the bind was successful.
     *
     * @name Queue#bind
     * @event
     */
    handler.addListener('Amqp.Queue.BindOk', function(){
        queue.emit('bind');
    });
    /**
     * Confirms a queue purge.
     *
     * This method confirms the purge of a queue.
     *
     * @name Queue#purge
     * @event
     * @param {Number} messageCount Reports the number of messages purged.
     */
    handler.addListener('Amqp.Queue.PurgeOk', function(frame){
        queue.emit('purge', frame.method.arguments.messageCount);
    });
    /**
     * Confirm deletion of a queue.
     *
     * This method confirms the deletion of a queue.
     *
     * @name Queue#delete
     * @event
     * @param {Number} messageCount Reports the number of messages deleted.
     */
    handler.addListener('Amqp.Queue.DeleteOk', function(frame){
        queue.emit('delete', frame.method.arguments.messageCount);
    });
}
require('sys').inherits(Queue, require('events').EventEmitter);
/**
 * Declare queue, create if needed.
 *
 * This method creates or checks a queue. When creating a new queue the client can specify various
 * properties that control the durability of the queue and its contents, and the level of sharing
 * for the queue.
 *
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param queue The queue name identifies the queue within the vhost. Queue names may consist of
 *      any mixture of digits, letters, and underscores.
 * @param passive If set <code>true</code>, the server will not create the queue. The client can
 *      use this to check whether a queue exists without modifying the server state.
 * @param durable If set <code>true</code> when creating a new queue, the queue will be marked as
 *      durable. Durable queues remain active when a server restarts. Non-durable queues (transient
 *      queues) are purged if/when a server restarts. Note that durable queues do not necessarily
 *      hold persistent messages, although it does not make sense to send persistent messages to a
 *      transient queue.
 * @param exclusive Exclusive queues may only be consumed from by the current connection. Setting
 *      the 'exclusive' flag always implies 'auto-delete'.
 * @param autoDelete If set <code>true</code>, the queue is deleted when all consumers have
 *      finished using it. Last consumer can be cancelled either explicitly or because its channel
 *      is closed. If there was no consumer ever on the queue, it won't be deleted.
 * @param nowait If set <code>true</code>, the server will not respond to the method. The client
 *      should not wait for a reply method. If the server could not complete the method it will
 *      raise a channel or connection exception.
 * @param args A set of arguments for the declaration. The syntax and semantics of these arguments
 *      depends on the server implementation. This field is ignored if passive is
 *      <code>true</code>.
 */
Queue.prototype.declare = function(/**Number*/ticket, /**String*/queue, /**Boolean*/passive,
        /**Boolean*/durable, /**Boolean*/exclusive, /**Boolean*/autoDelete, /**Boolean*/nowait,
        /**Object*/args){
    this.handler.call(Amqp.Class.Queue, Amqp.Class.Queue.Declare, { ticket: ticket, queue: queue,
        passive: passive, durable: durable, exclusive: exclusive, autoDelete: autoDelete,
        nowait: nowait, arguments: args});
};
/**
 * Bind queue to an exchange.
 *
 * This method binds a queue to an exchange. Until a queue is bound it will not receive any
 * messages. In a classic messaging model, store-and-forward queues are bound to a dest exchange
 * and subscription queues are bound to a dest_wild exchange.
 *
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param queue The queue name identifies the queue within the vhost. Queue names may consist of
 *      any mixture of digits, letters, and underscores.
 * @param exchange The exchange name is a client-selected string that identifies the exchange for
 *      publish methods. Exchange names may consist of any mixture of digits, letters, and
 *      underscores. Exchange names are scoped by the virtual host.
 * @param routingKey Specifies the routing key for the binding. The routing key is used for routing
 *      messages depending on the exchange configuration. Not all exchanges use a routing key -
 *      refer to the specific exchange documentation. If the routing key is empty and the queue
 *      name is empty, the routing key will be the current queue for the channel, which is the last
 *      declared queue.
 * @param nowait If set <code>true</code>, the server will not respond to the method. The client
 *      should not wait for a reply method. If the server could not complete the method it will
 *      raise a channel or connection exception.
 * @param args A set of arguments for the binding. The syntax and semantics of these arguments
 *      depends on the exchange class.
 */
Queue.prototype.bind = function(/**Number*/ticket, /**String*/queue, /**String*/exchange,
        /**String*/routingKey, /**Boolean*/nowait, /**Object*/args){
    this.handler.call(Amqp.Class.Queue, Amqp.Class.Queue.Bind, { ticket: ticket, queue: queue,
        exchange: exchange, routingKey: routingKey, nowait: nowait, arguments: args });
};
/**
 * Delete a queue.
 *
 * This method deletes a queue. When a queue is deleted any pending messages are sent to a
 * dead-letter queue if this is defined in the server configuration, and all consumers on the queue
 * are cancelled.
 *
 * @name Queue#delete
 * @function
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param queue The queue name identifies the queue within the vhost. Queue names may consist of
 *      any mixture of digits, letters, and underscores.
 * @param ifUnused If set <code>true</code>, the server will only delete the queue if it has no
 *      consumers. If the queue has consumers the server does does not delete it but raises a
 *      channel exception instead.
 * @param ifEmpty If set <code>true</code>, the server will only delete the queue if it has no
 *      messages. If the queue is not empty the server raises a channel exception.
 * @param nowait If set <code>true</code>, the server will not respond to the method. The client
 *      should not wait for a reply method. If the server could not complete the method it will
 *      raise a channel or connection exception.
 */
Queue.prototype['delete'] = function(/**Number*/ticket, /**String*/queue, /**Boolean*/ifUnused,
        /**Boolean*/ifEmpty, /**Boolean*/nowait){
    this.handler.call(Amqp.Class.Queue, Amqp.Class.Queue.Delete, { ticket: ticket, queue: queue,
        ifUnused: ifUnused, ifEmpty: ifEmpty, nowait: nowait });
};
/**
 * Purge a queue.
 *
 * This method removes all messages from a queue. It does not cancel consumers. Purged messages are
 * deleted without any formal "undo" mechanism.
 *
 * @param ticket An access ticket granted by the server for a certain set of access rights within a
 *      specific realm. Access tickets are valid within the channel where they were created, and
 *      expire when the channel closes.
 * @param queue The queue name identifies the queue within the vhost. Queue names may consist of
 *      any mixture of digits, letters, and underscores.
 * @param nowait If set, the server will not respond to the method. The client should not wait for
 *      a reply method. If the server could not complete the method it will raise a channel or
 *      connection exception.
 */
Queue.prototype.purge = function(/**Number*/ticket, /**String*/queue, /**Boolean*/nowait){
    this.handler.call(Amqp.Class.Queue, Amqp.Class.Queue.Purge, { ticket: ticket, queue: queue,
        nowait: nowait });
};
exports.Queue = Queue;
